﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using PSE.Framework.Versions.Common.Gateway;
using PSE.Framework.Versions.Common.Entities;
using PSE.Framework.Versions.Common.Configuration;
using PSE.Framework.Versions.Common;
using System.Diagnostics;

namespace PSE.Framework.Versions.Engine
{
    public class VersionsDiscovery
    {
        #region [ Singleton ]
        private VersionsDiscovery() { }
        private static object _lock = new object();
        private static VersionsDiscovery _instance;
        public static VersionsDiscovery Instance
        {
            get
            {
                lock (_lock)
                {
                    if (_instance == null)
                        _instance = new VersionsDiscovery();

                    return _instance;
                }
            }
        }
        #endregion [ Singleton ]

        private const string CONST_HTML = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><title>{HEADER}</title><style type=\"text/css\">body{margin: 0px;padding: 0px;font-family: Verdana; font-size:12px;}td{font-family: Verdana; font-size:12px;}.number{text-align: right;}</style></head><body><table width=\"100%\" border=\"0\" cellpadding=\"5\"><tr><td colspan=\"4\"><b>{HEADER}</b></td></tr><tr><td colspan=\"4\"><p align=\"justify\"><br />Verifique abaixo quais os m&oacute;dulos instalados em seu computador e as vers&otilde;es dos mesmos.<br>Utilize essa informa&ccedil;&atilde;o caso preciso falar com nosso suporte ou para comparar com atualiza&ccedil;&otilde;es disponibilizadas pela BM&FBovespa.<br /></p><table id=\"tabela\" width=\"900px\" border=\"1\" bordercolor=\"silver\" cellspacing=\"0\" cellpadding=\"2\"><thead><tr bgcolor=\"#EBEBEB\"><td nowrap=\"nowrap\" width=\"50px\"><b>M&oacute;dulo</b></td><td nowrap=\"nowrap\" width=\"200px\"><b>Cliente</b></td><td nowrap=\"nowrap\" width=\"90px\" align=\"center\"><b>Servidor</b></td><td nowrap=\"nowrap\" width=\"120px\" align=\"center\"><b>Url Servidor</b></td></tr></thead>{ROWS}</table></td></tr>{FOOTER}</table></body></html>";

        public Product Get(string productName, int majorVersion)
        {
            if (string.IsNullOrEmpty(productName))
                throw new ArgumentNullException("productName");

            List<Product> products = new List<Product>();

            LocalDiscovery local = new LocalDiscovery();
            Product productClient = local.Get(productName, majorVersion, Constants.SERVER_LOCALHOST);
            products.Add(productClient);

            var allServers = VersionsConfiguration.Instance.GetAllServers(productName, majorVersion);
            if (allServers != null)
            {
                foreach (var server in allServers)
                {
                    if (!server.ServerName.Equals(Constants.SERVER_LOCALHOST, StringComparison.InvariantCultureIgnoreCase))
                    {
                        NetworkDiscovery network = new NetworkDiscovery(server.ToString());
                        Product productNetwork = network.Get(productName, majorVersion, server.ServerName);
                        if (productNetwork != null)
                        {
                            products.Add(productNetwork);
                        }
                    }
                }
            }

            Product mainProduct = MergeModules(products);
            return mainProduct;
        }

        public void CreateReport(Product product, string path)
        {
            if (product == null)
                throw new ArgumentNullException("product");

            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");

            string header = string.Format("{0} v{1}", product.Name.ToUpper(), product.MajorVersion);
            StringBuilder sb = new StringBuilder();
            foreach (var module in product.Modules)
            {
                sb.Append("<tr>");
                sb.AppendLine(CreateTD(module.ModuleName));
                sb.AppendLine(CreateTD(module.Versions.Client));
                sb.AppendLine(CreateTD(module.Versions.Server));
                sb.AppendLine(CreateTD(module.Versions.ServerUrl));
                sb.Append("</tr>");
            }
            string footer = string.Format("<tr><td colspan=\"4\">Gerado em : {0} </td></tr>", DateTime.Now.ToString());

            string html = CONST_HTML.Replace("{HEADER}", header).Replace("{ROWS}", sb.ToString()).Replace("{FOOTER}", footer);

            var file = System.IO.File.CreateText(path);
            file.Write(html);
            file.Close();

            try
            {
                Process process = new Process();
                process.StartInfo = new ProcessStartInfo(path);
                process.Start();
            }
            catch{}
        }

        private string CreateTD(string content)
        {
            string td = string.Format("<td>{0}</td>", content);
            return td;
        }

        private Product MergeModules(List<Product> products)
        {
            if (products == null)
                throw new ArgumentNullException("products");

            Product newProduct = new Product();
            newProduct.Name = products[0].Name;
            newProduct.MajorVersion = products[0].MajorVersion;

            Dictionary<string, Module> modules = new Dictionary<string, Module>();

            foreach (var product in products)
                AddModule(ref modules, product);

            foreach (var product in products)
                GetModuleVersions(ref modules, product);

            newProduct.Modules = modules.Values.Select(m => m).ToList();
            return newProduct;
        }

        private void AddModule(ref Dictionary<string, Module> modules, Product product)
        {
            foreach (var module in product.Modules)
                if (!modules.ContainsKey(module.Folder))
                    modules.Add(module.Folder, module);
        }

        private void GetModuleVersions(ref Dictionary<string, Module> modules, Product product)
        {
            foreach (var module in product.Modules)
                SetModuleVersion(ref modules, module);
        }

        private void SetModuleVersion(ref Dictionary<string, Module> modules, Module module)
        {
            if (modules.ContainsKey(module.Folder))
            {
                Module selectedModule = modules[module.Folder];

                selectedModule.Versions.ModuleName = module.Versions.ModuleName;
                selectedModule.Versions.ModuleVersion = module.Versions.ModuleVersion;

                if (!string.IsNullOrEmpty(module.Versions.Client))
                    if(module.Versions.ServerUrl.Equals(Constants.SERVER_LOCALHOST, StringComparison.InvariantCultureIgnoreCase)) 
                        selectedModule.Versions.Client = module.Versions.Client;

                if (!string.IsNullOrEmpty(module.Versions.Database))
                    selectedModule.Versions.Database = module.Versions.Database;

                if (!string.IsNullOrEmpty(module.Versions.Server))
                {
                    selectedModule.Versions.Server = module.Versions.Server;
                    selectedModule.Versions.ServerUrl = module.Versions.ServerUrl;
                }
            }
        }
    }
}